home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / expanded.lha / expanded / src / Space.C < prev    next >
C/C++ Source or Header  |  1992-03-19  |  71KB  |  2,597 lines

  1. //
  2. // Linear-Affine-Projective Geometry Package
  3. //
  4. // Space.C
  5. //
  6. // $Header$
  7. //
  8. // William J.R. Longabaugh 
  9. // University of Washington
  10. //
  11. // Implementation of the linear-affine-projective geometry
  12. // package described in William J.R. Longabaugh, "An Expanded
  13. // System for Coordinate-Free Geometric Programming", Master's 
  14. // thesis, University of Washington, 1992.
  15. //
  16. // Copyright (c) 1992, William J.R. Longabaugh
  17. //   Copying, use and development for non-commercial purposes permitted.
  18. //   All rights for commercial use reserved.
  19. //   This software is unsupported and without warranty; it is
  20. //   provided "as is".
  21. //
  22. // ***********************************************************************
  23.  
  24. #include <string.h>
  25. #include "Lap.h"
  26.  
  27. // ***********************************************************************
  28. //
  29. // Class for exclusive use of Space class to hold onto data for a 
  30. // space.  What is really wanted is a simple structure; I am not
  31. // really interested in data hiding here.  However, under g++ 1.37.1,
  32. // this apparently MUST be a class, not a struct, so that virtual 
  33. // ptrs of class members are initialized.  Also, the fact that class
  34. // members will be automatically initialized using null constructors
  35. // is desirable.  Thus, this is a class, but note that all members
  36. // are public, allowing unlimited access.
  37.  
  38. // Constants to organize space set and standard affine map arrays:
  39.  
  40. const int SP_SET_SIZE = 6;
  41.  
  42. const int NUM_SLOT = 3;
  43. const int AFFSLOT = 0;
  44. const int LINSLOT = 1;
  45. const int PCSLOT = 2;
  46.  
  47. class SpaceInfo {
  48.  
  49.   public:
  50.  
  51.     SpaceType type;            // What type of space it is
  52.     SRel thisSpace;            // Position of this space in 6-set
  53.     int dim;             // The dimension of the space
  54.     char name[MAX_NAMESIZE];     // Space name
  55.     Basis stdBasis;         // Predefined Basis
  56.     int matsize;            // Size of matrix reps
  57.     GeObType native;        // Native GeOb type
  58.  
  59.     int cpSize;            // Number of spaces, if a CPSpace
  60.     SpaceList cpSpaces;        // Constituent spaces (if CPSize > 1)
  61.     IntList cpSlots;        // Starting slots for components
  62.  
  63.     Space spaceSet[SP_SET_SIZE];     // Other spaces in space set
  64.     VSpace dual;             // Dual space
  65.  
  66.     ProjectiveMap stdPMap;        // Standard Projective Map
  67.         AffineMap stdAMap[NUM_SLOT];     // Standard Affine Maps
  68.     LinearMap stdLMap;        // Standard Linear Map
  69.  
  70.     Boolean     isEuclidean;        // True if space is Euclidean
  71.     MLM      innerProd;        // Standard Inner Product
  72.     MLM     crossProd;        // Standard Cross Product
  73.  
  74.     GeObList atInfinity;        // Set of points at infinity.
  75.     Matrix     hoistTangent;         // Gets tan. vec. to affine rep.
  76.  
  77.     ASubSet stdAffineSet;         // Std. affine subset of space
  78.     SubSet fullset;            // SubSet for whole space
  79.     PSubSet fullproj;        // Peoj. SubSet for whole space
  80.  
  81. // Constructors/Destructors:
  82.  
  83.         SpaceInfo(void);          // Null constructor
  84.         ~SpaceInfo(void);         // Destructor
  85.         SpaceInfo(char* namein, int d); // Used to build error info block
  86. };
  87.  
  88. // ***********************************************************************
  89. //
  90. // Declare the existence of the error info block:
  91.  
  92. static SpaceInfo errinfo;
  93.  
  94. // ***********************************************************************
  95. // ***********************************************************************
  96. //
  97. // SpaceInfo Class
  98. //
  99. // ***********************************************************************
  100. // ***********************************************************************
  101. //
  102. // Null constructor.  Nothing needs to be done.  Fortunately, the 
  103. // null constructors of object class members are also called automatically,
  104. // so they are all initialized to null objects (which is important).
  105. // This is too large to inline in g++.
  106. //
  107.  
  108. SpaceInfo::SpaceInfo(void) {}
  109.  
  110. // ***********************************************************************
  111. //
  112. // Destructor.  Don't actually need this, but it suppresses a g++ 1.37
  113. // compiler warning.  It is also too large to inline.
  114.  
  115. SpaceInfo::~SpaceInfo(void) {}
  116.  
  117. // ***********************************************************************
  118. //
  119. // Special constructor used to build an "error info block".  Uninitialized
  120. // spaces point to that block.
  121.  
  122. SpaceInfo::SpaceInfo(char* namein, int d)
  123. {
  124.   type = NULL_SPACE;
  125.   dim = d;
  126.   thisSpace= NO_RELATION;
  127.   matsize = 0;
  128.   native = NULL_GEOB;
  129.   cpSize = 0;
  130.   isEuclidean = FALSE;
  131.  
  132. // Local copy of the debug name:
  133.  
  134.   strncpy(name, namein, MAX_NAMESIZE - 1);
  135.   name[MAX_NAMESIZE - 1] = '\0';
  136. }
  137.  
  138. // ***********************************************************************
  139. // ***********************************************************************
  140. //
  141. // Space Class
  142. //
  143. // ***********************************************************************
  144. // ***********************************************************************
  145. //
  146. // Private/protected member functions
  147. //
  148. // ***********************************************************************
  149. //
  150. // NOTE: The following few functions are PERFECT candidates for inlining.
  151. // However, because they reference items in a SpaceInfo, they cannot be
  152. // defined in the Space class declaration.  (The SpaceInfo class must
  153. // be declared following the List classes, which must in turn be declared
  154. // after the Space class.)  While the "inline" keyword could be used
  155. // to declare the function inline when they are defined, the CFRONT 1.2
  156. // compiler appears to have a bug that occasionally shows up when this
  157. // is done.  Because of this problem, it was decided that the only inline
  158. // functions in this system would be those defined in the class
  159. // declaration.
  160. //
  161. // ***********************************************************************
  162. // 
  163. // Note it is the responsibility of caller to check validity of bounds:
  164.  
  165. int Space::StartSlot(int n) {return (info->cpSlots[n]);}
  166.  
  167. // ***********************************************************************
  168.  
  169. int Space::MatrixSize(void) {return (info->matsize);}
  170.  
  171. // ***********************************************************************
  172.  
  173. Matrix& Space::HoistTangent(void) {return (info->hoistTangent);}
  174.  
  175. // ***********************************************************************
  176. // 
  177. // User is responsible for updating space set independently!
  178.  
  179. inline void Space::SetDual(Space& s) {info->dual = s;}
  180.  
  181. // ***********************************************************************
  182.  
  183. void Space::SetStdPMap(Map& m) {info->stdPMap = m;}
  184.  
  185. // ***********************************************************************
  186.  
  187. void Space::SetStdLMap(Map& m) {info->stdLMap = m;}
  188.  
  189. // ***********************************************************************
  190.  
  191. void Space::SetStdAMap(SRel s, Map& m)
  192. {
  193.   switch (s) {
  194.     case LINEARIZATION:
  195.       info->stdAMap[LINSLOT] = m;
  196.       break;
  197.     case PROJECT_COMP: 
  198.       info->stdAMap[PCSLOT] = m;
  199.       break;
  200.     case AFFINE: 
  201.       info->stdAMap[AFFSLOT] = m;
  202.       break;
  203.     case TANGENT:
  204.     case LIN_DUAL: 
  205.     case TANG_DUAL: 
  206.     case NO_RELATION:
  207.     case SAME_SPACE:
  208.     default:
  209.       errh.ErrorExit("void Space::SetStdAMap(SRel, Map&)",
  210.                      "Unexpected Relation",
  211.               ErrType("Space relation specified =", s, SRELTYPES),
  212.               *this, m);
  213.       break;
  214.   }
  215.  
  216.   info->stdAffineSet = m.Domain();
  217.  
  218.   if (info->thisSpace == PROJECT_COMP) {
  219.     info->atInfinity = m.Domain().AtInfinity();
  220.   }
  221. }
  222.  
  223. // ***********************************************************************
  224.  
  225. void Space::SetSpaceSet(SRel r, Space& sp)
  226. {
  227.   if (r >= (int)NO_RELATION) {
  228.     errh.ErrorExit("void Space::SetSpaceSet(SRel, Space&)",
  229.                    "Invalid relation specified",
  230.             ErrType("Space relation specified =", r, SRELTYPES),
  231.             *this, sp);
  232.   }
  233.   info->spaceSet[(int) r] = sp;
  234. }
  235.  
  236. // ***********************************************************************
  237. // 
  238. // This private method broadcasts the existence of a newly created space
  239. // to all other spaces in the set.  It assumes the set of the new space
  240. // has been initialized to null spaces (except for its own slot).  The
  241. // SRel argument refers to the relation of this space.
  242. //
  243.  
  244. void Space::Broadcast(SRel s, Space& ins) 
  245. {
  246. // The space we were handed gives all the spaces that are related to this
  247. // space.  We need to fill this information in, AND broadcast the existence
  248. // of this new space to the other spaces in the set:
  249.  
  250.   for (int i = 0; i < SP_SET_SIZE; i++) {
  251.     if ((SRel)i == s) {
  252.       ins.SetSpaceSet(s, *this);
  253.     } else if (ins.HasSpace((SRel)i)) {
  254.       Space temp = ins.GetSpace((SRel)i);
  255.       info->spaceSet[i] = temp;
  256.       temp.SetSpaceSet(s, *this);
  257.     }
  258.   }
  259. }
  260.  
  261. // ***********************************************************************
  262. // 
  263. // This function merges two independent space sets into a single set.
  264. //
  265.  
  266. void Space::MergeSets(Space& set2) 
  267. {
  268.  
  269. // Make this space's set up to date by merging the two lists.  Then
  270. // for everybody on this new list (except this space) tell them about
  271. // all the spaces on the merged list:
  272.  
  273.   int i;
  274.   Space hold;
  275.  
  276.   for (i = 0; i < SP_SET_SIZE; i++) {
  277.     if (set2.HasSpace((SRel)i)) {
  278.       info->spaceSet[i] = set2.GetSpace((SRel)i);
  279.     }
  280.   }
  281.  
  282.   for (i = 0; i < SP_SET_SIZE; i++) {
  283.     hold = info->spaceSet[i];    
  284.     if ((hold != *this) && (hold.Holds() != NULL_SPACE)) {
  285.       for (int j = 0; j < SP_SET_SIZE; j++) {
  286.         if (!hold.HasSpace((SRel)j)) {
  287.       hold.SetSpaceSet((SRel)j, info->spaceSet[j]);
  288.         }
  289.       }
  290.     }
  291.   }
  292. }
  293.  
  294. // ***********************************************************************
  295. // 
  296. // This function copies only a maximum number of characters into
  297. // the debug name buffer.
  298. //
  299.  
  300. void Space::CopyDebugName(char* buf)
  301. {
  302.   strncpy(info->name, buf, MAX_NAMESIZE - 1);
  303.   info->name[MAX_NAMESIZE - 1] = '\0';
  304.   return;
  305. }
  306.  
  307. // ***********************************************************************
  308. // 
  309. // This function builds a tagged debug name.  The user is responsible
  310. // for calling DestroyTagName() when finished.
  311. //
  312.  
  313. char* Space::BuildTagName(char* tag, Space& s) 
  314. {
  315.   int len = strlen(tag);
  316.   char* buf = new char[MAX_NAMESIZE + len];
  317.  
  318.   strncpy(buf, tag, len);
  319.   s.Name(buf + len);
  320.   return (buf);
  321. }
  322.  
  323. // ***********************************************************************
  324. //
  325. // Destroys a tagged debug name:
  326. //
  327.  
  328. void Space::DestroyTagName(char* buf) {delete buf;}
  329.  
  330. // ***********************************************************************
  331. // 
  332. // Evaluate the linkage between two given spaces.  They are unlinked,
  333. // linked to each other, or erroneously linked to other spaces:
  334. //
  335.  
  336. Boolean Space::HaveLink(Space& s1, SRel r1,
  337.             Space& s2, SRel r2, Boolean* have_error) 
  338. {
  339.   Boolean linked = FALSE;
  340.   Boolean s2linked = FALSE;
  341.   Space s1c;
  342.   Space s2c;
  343.  
  344.   if (s1.HasSpace(r2)) {
  345.     s1c = s1.GetSpace(r2);
  346.     linked = TRUE;
  347.   }
  348.  
  349.   if (s2.HasSpace(r1)) {
  350.     s2c = s2.GetSpace(r1);
  351.     s2linked = TRUE;
  352.   }
  353.  
  354.   if ((linked && (s1c != s2)) || (s2linked && (s2c != s1))) {
  355.     *have_error = TRUE;
  356.   } else {
  357.     *have_error = FALSE;
  358.   }
  359.  
  360.   return linked;
  361. }
  362.  
  363. // ***********************************************************************
  364. //
  365. // The following group of functions are used to link spaces together
  366. // with standard maps.  A variety of functions are needed to handle
  367. // the many different cases of how the spaces may be already linked.
  368. //
  369. // ***********************************************************************
  370. // 
  371. // Links the Tangent space to the Linearization.  The LA link must
  372. // already exist (or the tangent space would not exist), so the 
  373. // map between them exists.
  374. //
  375.  
  376. void Space::LinkLT(void)
  377. {
  378.   Space T = this->GetSpace(TANGENT);
  379.   Space L = this->GetSpace(LINEARIZATION);
  380.   Space A = this->GetSpace(AFFINE);
  381.  
  382.   LinearMap m = (A.AffineMapTo(LINEARIZATION)).AssocLinear();
  383.   T.SetStdLMap(m);
  384.   L.SetStdLMap(m.Inv());
  385.   return;
  386. }
  387.  
  388. // ***********************************************************************
  389. // 
  390. // Links the Affine space to the Projective Completion, where there
  391. // are no preexisting links:
  392. //
  393.  
  394. void Space::LinkAP(AffineMap& m)
  395. {
  396.   Space A = this->GetSpace(AFFINE);
  397.   Space P = this->GetSpace(PROJECT_COMP);
  398.  
  399.   A.SetStdAMap(PROJECT_COMP, m);
  400.   P.SetStdAMap(AFFINE, m.Inv());
  401.   return;
  402. }
  403.  
  404. // ***********************************************************************
  405. // 
  406. // Links the Linearization space to Affine space, where there
  407. // are no preexisting links:
  408. //
  409.  
  410. void Space::LinkLA(AffineMap& m)
  411. {
  412.   Space L = this->GetSpace(LINEARIZATION);
  413.   Space A = this->GetSpace(AFFINE);
  414.   AffineMap mi = m.Inv();
  415.   
  416.   L.SetStdAMap(AFFINE, m);
  417.   A.SetStdAMap(LINEARIZATION, mi);
  418.  
  419.   if (this->HasSpace(TANGENT)) {
  420.     Space T = this->GetSpace(TANGENT);
  421.     LinearMap mia = mi.AssocLinear();
  422.     T.SetStdLMap(mia);
  423.     L.SetStdLMap(mia.Inv());
  424.   }
  425.   return;
  426. }
  427.  
  428. // ***********************************************************************
  429. // 
  430. // Links the Linearization space to the Projective Completion, where
  431. // there are no preexisting links:
  432. //
  433.  
  434. void Space::LinkLP(ProjectiveMap& m)
  435. {
  436.   Space L = this->GetSpace(LINEARIZATION);
  437.   Space P = this->GetSpace(PROJECT_COMP);
  438.  
  439.   L.SetStdPMap(m);
  440.   P.SetStdPMap(m.Inv());
  441.   return;
  442. }
  443.  
  444. // ***********************************************************************
  445. // 
  446. // Links the Linearization space to Affine space, where there
  447. // is a link from Lin to PC:
  448. //
  449.  
  450. void Space::LinkLAHaveLP(AffineMap& m)
  451. {
  452.   Space L = this->GetSpace(LINEARIZATION);
  453.   Space A = this->GetSpace(AFFINE);
  454.   Space P = this->GetSpace(PROJECT_COMP);
  455.   AffineMap mi = m.Inv();
  456.   
  457.   L.SetStdAMap(AFFINE, m);
  458.   A.SetStdAMap(LINEARIZATION, mi);
  459.  
  460.   if (this->HasSpace(TANGENT)) {
  461.     Space T = this->GetSpace(TANGENT);
  462.     LinearMap mia = mi.AssocLinear();
  463.     T.SetStdLMap(mia);
  464.     L.SetStdLMap(mia.Inv());
  465.   }
  466.  
  467. // Since a standard projective map exists, the AP map must be derived:
  468.  
  469.   AffineMap ap(L.ProjectiveMapTo(PROJECT_COMP), m);
  470.  
  471.   A.SetStdAMap(PROJECT_COMP, ap);
  472.   P.SetStdAMap(AFFINE, ap.Inv());
  473.  
  474. // Finally compose the affine maps to get the LP affine map:
  475.  
  476.   AffineMap lp = ap.Compose(m); 
  477.  
  478.   L.SetStdAMap(PROJECT_COMP, lp);
  479.   P.SetStdAMap(LINEARIZATION, lp.Inv());
  480.   return;
  481. }
  482.  
  483. // ***********************************************************************
  484. // 
  485. // Links the Affine space to the Projective Completion, where there
  486. // is a link from Lin to PC:
  487. //
  488.  
  489. void Space::LinkAPHaveLP(AffineMap& m)
  490. {
  491.   Space L = this->GetSpace(LINEARIZATION);
  492.   Space A = this->GetSpace(AFFINE);
  493.   Space P = this->GetSpace(PROJECT_COMP);
  494.  
  495.   A.SetStdAMap(PROJECT_COMP, m);
  496.   P.SetStdAMap(AFFINE, m.Inv());
  497.  
  498. // Standard projective PL map exists, so LA map must be derived:
  499.  
  500.   AffineMap la(m, L.ProjectiveMapTo(PROJECT_COMP));
  501.  
  502.   A.SetStdAMap(LINEARIZATION, la.Inv());
  503.   L.SetStdAMap(AFFINE, la);
  504.  
  505. // Compose the affine maps to get the LP affine map:
  506.  
  507.   AffineMap lp = m.Compose(L.AffineMapTo(AFFINE)); 
  508.  
  509.   L.SetStdAMap(PROJECT_COMP, lp);
  510.   P.SetStdAMap(LINEARIZATION, lp.Inv());
  511.  
  512. // Fill in standard linear map, if tangent space exists:
  513.  
  514.   if (this->HasSpace(TANGENT)) {
  515.     Space T = this->GetSpace(TANGENT);
  516.     LinearMap ala = la.Inv().AssocLinear();
  517.     T.SetStdLMap(ala);
  518.     L.SetStdLMap(ala.Inv());
  519.   }
  520.   return;
  521. }
  522.  
  523. // ***********************************************************************
  524. // 
  525. // Links the Linearization space to Affine space, where there
  526. // is a link from Aff to PC:
  527. //
  528.  
  529. void Space::LinkLAHaveAP(AffineMap& m)
  530. {
  531.   Space L = this->GetSpace(LINEARIZATION);
  532.   Space A = this->GetSpace(AFFINE);
  533.   Space P = this->GetSpace(PROJECT_COMP);
  534.   AffineMap mi = m.Inv();
  535.   
  536.   L.SetStdAMap(AFFINE, m);
  537.   A.SetStdAMap(LINEARIZATION, mi);
  538.  
  539.   if (this->HasSpace(TANGENT)) {
  540.     Space T = this->GetSpace(TANGENT);
  541.     LinearMap mia = mi.AssocLinear();
  542.     T.SetStdLMap(mia);
  543.     L.SetStdLMap(mia.Inv());
  544.   }
  545.  
  546. // Compose the affine maps to get the LP affine map:
  547.  
  548.   AffineMap lp = A.AffineMapTo(PROJECT_COMP).Compose(m); 
  549.  
  550.   L.SetStdAMap(PROJECT_COMP, lp);
  551.   P.SetStdAMap(LINEARIZATION, lp.Inv());
  552.  
  553. // Now derive a consistent projective map for lin-pc link:
  554.  
  555.   ProjectiveMap plp(L, lp, P);
  556.  
  557.   L.SetStdPMap(plp);
  558.   P.SetStdPMap(plp.Inv());
  559.   return;
  560. }
  561.  
  562. // ***********************************************************************
  563. // 
  564. // Links the Affine space to the Projective Completion, where there
  565. // is a link from Lin to Aff:
  566. //
  567.  
  568. void Space::LinkAPHaveLA(AffineMap& m)
  569. {
  570.   Space L = this->GetSpace(LINEARIZATION);
  571.   Space A = this->GetSpace(AFFINE);
  572.   Space P = this->GetSpace(PROJECT_COMP);
  573.  
  574.   A.SetStdAMap(PROJECT_COMP, m);
  575.   P.SetStdAMap(AFFINE, m.Inv());
  576.  
  577. // Compose the affine maps to get the LP affine map:
  578.  
  579.   AffineMap lp = m.Compose(L.AffineMapTo(AFFINE)); 
  580.  
  581.   L.SetStdAMap(PROJECT_COMP, lp);
  582.   P.SetStdAMap(LINEARIZATION, lp.Inv());
  583.  
  584. // Now derive a consistent projective map for lin-pc link:
  585.  
  586.   ProjectiveMap plp(L, lp, P);
  587.  
  588.   L.SetStdPMap(plp);
  589.   P.SetStdPMap(plp.Inv());
  590.   return;
  591. }
  592.  
  593. // ***********************************************************************
  594. // 
  595. // Links the Linearization space to the Projective Completion, where
  596. // is a link from Lin to Aff:
  597. //
  598.  
  599. void Space::LinkLPHaveLA(ProjectiveMap& m)
  600. {
  601.   Space L = this->GetSpace(LINEARIZATION);
  602.   Space A = this->GetSpace(AFFINE);
  603.   Space P = this->GetSpace(PROJECT_COMP);
  604.   
  605.   L.SetStdPMap(m);
  606.   P.SetStdPMap(m.Inv());
  607.  
  608. // Since a standard projective map now exists, the AP map must be derived:
  609.  
  610.   AffineMap ap(m, L.AffineMapTo(AFFINE));
  611.  
  612.   A.SetStdAMap(PROJECT_COMP, ap);
  613.   P.SetStdAMap(AFFINE, ap.Inv());
  614.  
  615. // Finally compose the affine maps to get the LP affine map:
  616.  
  617.   AffineMap lp = ap.Compose(L.AffineMapTo(AFFINE)); 
  618.  
  619.   L.SetStdAMap(PROJECT_COMP, lp);
  620.   P.SetStdAMap(LINEARIZATION, lp.Inv());
  621.   return;
  622. }
  623.  
  624. // ***********************************************************************
  625. // 
  626. // Links the Linearization space to the Projective Completion, where
  627. // is a link from Aff to PC:
  628. //
  629.  
  630. void Space::LinkLPHaveAP(ProjectiveMap& m)
  631. {
  632.   Space L = this->GetSpace(LINEARIZATION);
  633.   Space A = this->GetSpace(AFFINE);
  634.   Space P = this->GetSpace(PROJECT_COMP);
  635.   ProjectiveMap mi = m.Inv();
  636.  
  637.   L.SetStdPMap(m);
  638.   P.SetStdPMap(mi);
  639.  
  640. // Standard affine AP map exists, so LA map must be derived:
  641.  
  642.   AffineMap ap = A.AffineMapTo(PROJECT_COMP);
  643.   AffineMap la(ap, m);
  644.  
  645.   A.SetStdAMap(LINEARIZATION, la.Inv());
  646.   L.SetStdAMap(AFFINE, la);
  647.  
  648. // Compose the affine maps to get the LP affine map:
  649.  
  650.   AffineMap lp = ap.Compose(L.AffineMapTo(AFFINE)); 
  651.  
  652.   L.SetStdAMap(PROJECT_COMP, lp);
  653.   P.SetStdAMap(LINEARIZATION, lp.Inv());
  654.  
  655. // Fill in standard linear map, if tangent space exists:
  656.  
  657.   if (this->HasSpace(TANGENT)) {
  658.     Space T = this->GetSpace(TANGENT);
  659.     LinearMap ala = la.Inv().AssocLinear();
  660.     T.SetStdLMap(ala);
  661.     L.SetStdLMap(ala.Inv());
  662.   }
  663.   return;
  664. }
  665.  
  666. // ***********************************************************************
  667. //
  668. // Returns a REFERENCE to the standard affine map to the specified
  669. // space in the six-space set.  Only used by the implementing classes. 
  670. //
  671.  
  672. AffineMap& Space::AffineMapToRef(SRel s)
  673. {
  674.   static char* sig = "AffineMap Space::AffineMapToRef(SRel)";
  675.   Boolean errval = FALSE;
  676.  
  677. // Need to get the space first to insure it is created.  Note if
  678. // we are trying to get from linearization to projective with affine
  679. // map, the intervening affine space must be created also.  LIN to PC
  680. // links without an affine space are purely projective; standard
  681. // affine map is only created when affine space is plugged in.
  682.  
  683.   if (((info->thisSpace == LINEARIZATION) && (s == PROJECT_COMP)) ||
  684.       ((info->thisSpace == PROJECT_COMP) && (s == LINEARIZATION))) {
  685.     this->GetSpace(AFFINE);
  686.   }
  687.  
  688.   this->GetSpace(s);
  689.  
  690.   if (info->thisSpace == LINEARIZATION) {
  691.     if (s == AFFINE) {
  692.       return info->stdAMap[AFFSLOT];
  693.     } else if (s == PROJECT_COMP) {
  694.       return info->stdAMap[PCSLOT];
  695.     } else {
  696.       errval = TRUE;
  697.     }
  698.   } else if (info->thisSpace == AFFINE) {
  699.     if (s == LINEARIZATION) {
  700.       return info->stdAMap[LINSLOT];
  701.     } else if (s == PROJECT_COMP) {
  702.       return info->stdAMap[PCSLOT];
  703.     } else {
  704.       errval = TRUE;
  705.     }
  706.   } else if (info->thisSpace == PROJECT_COMP) {
  707.     if (s == LINEARIZATION) {
  708.       return info->stdAMap[LINSLOT];
  709.     } else if (s == AFFINE) {
  710.       return info->stdAMap[AFFSLOT];
  711.     } else {
  712.       errval = TRUE;
  713.     }
  714.   } else {
  715.     errh.ErrorExit(sig, "No standard affine map from this space", *this);
  716.   }
  717.  
  718.   if (errval) {
  719.     errh.ErrorExit(sig, "No standard affine map to specified space",
  720.            ErrType("Space relation specified =", s, SRELTYPES),
  721.            *this);
  722.   }
  723. }
  724.  
  725. // ***********************************************************************
  726. // 
  727. // Returns a REFERENCE to the standard projective map to the specified
  728. // space in the six-space set.  Only used by the implementing classes. 
  729. //
  730.  
  731. ProjectiveMap& Space::ProjectiveMapToRef(SRel s)
  732. {
  733.  
  734. // Need to get the space first to insure it is created!
  735.  
  736.   this->GetSpace(s);
  737.  
  738.   if (((info->thisSpace == LINEARIZATION) && (s == PROJECT_COMP)) ||
  739.       (info->thisSpace == PROJECT_COMP) && (s == LINEARIZATION)) {
  740.     return info->stdPMap;
  741.   } else {
  742.     errh.ErrorExit("ProjectiveMap Space::ProjectiveMapToRef(SRel)",
  743.                    "No standard projective map to specified space",
  744.             ErrType("Space relation specified =", s, SRELTYPES),
  745.            *this);
  746.   }
  747. }
  748.  
  749. // ***********************************************************************
  750. // 
  751. // Returns a REFERENCE to the standard linear map to the specified
  752. // space in the six-space set.  Only used by the implementing classes. 
  753. //
  754.  
  755. LinearMap& Space::LinearMapToRef(SRel s)
  756. {
  757. // Need to get the space first to insure it is created!
  758.  
  759.   this->GetSpace(s);
  760.  
  761.   if (((info->thisSpace == LINEARIZATION) && (s == TANGENT)) ||
  762.       (info->thisSpace == TANGENT) && (s == LINEARIZATION)) {
  763.     return info->stdLMap;
  764.   } else {
  765.     errh.ErrorExit("LinearMap Space::LinearMapToRef(SRel)",
  766.                    "No standard linear map to specified space",
  767.             ErrType("Space relation specified =", s, SRELTYPES),
  768.            *this);
  769.   }
  770. }
  771.  
  772. // ***********************************************************************
  773. // 
  774. // Data dump for short form.
  775. //
  776.  
  777. void Space::data_out(ostream &c, int indent, char* name)
  778. {
  779.   char *ibloc = new char[indent + 1];
  780.   for (int i = 0; i < indent; i++) {
  781.     *(ibloc + i) = ' ';
  782.   }
  783.   *(ibloc + indent) = '\0';
  784.  
  785.   c << ibloc << ast;
  786.   c << ibloc << name;
  787.   c << ibloc << "Type of space: ";
  788.   SpaceTypeOut(c, type);
  789.   c << "\n";
  790.   c << ibloc << "Currently holds: ";
  791.   SpaceTypeOut(c, holds);
  792.   c << "\n";
  793.   if (holds != NULL_SPACE) {
  794.     c << ibloc << "Space relationship: ";
  795.     SRelOut(c, info->thisSpace);
  796.     c << "\n" << ibloc << "Name of space: " << info->name << "\n";
  797.     c << ibloc << "Dimension: " << info->dim << "\n";
  798.     c << ibloc << "Size of matrix representations: " << info->matsize << "\n";
  799.     c << ibloc << "Native type of object in space: ";
  800.     GeObTypeOut(c, info->native);
  801.     c << "\n";
  802.     c << ibloc << "Memory location: " << (long)info << "\n";
  803.     c << ibloc << "Number of constituent spaces: " << info->cpSize << "\n";
  804.  
  805.     if (info->cpSize > 1) {
  806.       c << ibloc << "Constituent spaces:\n";
  807.       for (i = 0; i < info->cpSize; i++) {
  808.         (info->cpSpaces[i]).debug_out(c, indent + ERR_IND);
  809.       }
  810.     }
  811.   }
  812.   c << ibloc << ast;
  813.  
  814.   delete ibloc;
  815.   return;
  816. }
  817.  
  818. // ***********************************************************************
  819. // 
  820. // This dumps ALL the data in the space.  It should not be 
  821. // be called by the debug output functions of any class that has a 
  822. // member in space, or infinite recursion will result.  
  823. //
  824.  
  825. void Space::heavy_data_out(ostream &c, int indent, char* name) 
  826. {
  827.   int i;
  828.  
  829.   char *ibloc = new char[indent + 1];
  830.   for (i = 0; i < indent; i++) {
  831.     *(ibloc + i) = ' ';
  832.   }
  833.   *(ibloc + indent) = '\0';
  834.  
  835.   c << ibloc << ast;
  836.   c << ibloc << name;
  837.   c << ibloc << "Type of space: ";
  838.   SpaceTypeOut(c, type);
  839.   c << "\n";
  840.   c << ibloc << "Currently holds: ";
  841.   SpaceTypeOut(c, holds);
  842.   c << "\n";
  843.   if (holds != NULL_SPACE) {
  844.     c << ibloc << "Space relationship: ";
  845.     SRelOut(c, info->thisSpace);
  846.     c << "\n" << ibloc << "Name of space: " << info->name << "\n";
  847.     c << ibloc << "Dimension: " << info->dim << "\n";
  848.     c << ibloc << "Memory location: " << (long)info << "\n";
  849.     c << ibloc << "Standard basis:\n";
  850.     info->stdBasis.debug_out(c, indent + ERR_IND);
  851.     c << ibloc << "Size of matrix representations: " << info->matsize << "\n";
  852.     c << ibloc << "Native type of object in space: ";
  853.     GeObTypeOut(c, info->native);
  854.     c << "\n";
  855.     c << ibloc << "Number of constituent spaces: " << info->cpSize << "\n";
  856.  
  857.     if (info->cpSize > 1) {
  858.       c << ibloc << "Constituent spaces:\n";
  859.       for (i = 0; i < info->cpSize; i++) {
  860.         (info->cpSpaces[i]).debug_out(c, indent + ERR_IND);
  861.       }
  862.  
  863.       c << ibloc << "Starting locations for each constituent:\n";
  864.       for (i = 0; i < info->cpSize; i++) {
  865.         c << ibloc << info->cpSlots[i];
  866.         if (i % 4 == 3) {c << "\n";}
  867.       }
  868.     }
  869.  
  870.     c << ibloc << "Other spaces in space set:\n";
  871.     for (i = 0; i < 6; i++) {
  872.       if ((info->spaceSet[i]).Holds() != NULL_SPACE) {
  873.         c << "\n" << ibloc;
  874.         SRelOut(c, i);
  875.         c << ":\n";
  876.         (info->spaceSet[i]).debug_out(c, indent + ERR_IND);
  877.       }
  878.     }
  879.  
  880.     if ((info->dual).Holds() != NULL_SPACE) {
  881.       c << ibloc << "Dual Space:\n";
  882.       info->dual.debug_out(c, indent + ERR_IND);
  883.     }
  884.  
  885.     c << ibloc << "Standard projective map:\n";
  886.     info->stdPMap.debug_out(c, indent + ERR_IND);
  887.     c << ibloc << "Standard affine maps:\n";
  888.     for (i = 0; i < NUM_SLOT; i++) {
  889.       info->stdAMap[i].debug_out(c, indent + ERR_IND);
  890.     }
  891.     c << ibloc << "Standard linear map:\n";
  892.     info->stdLMap.debug_out(c, indent + ERR_IND);
  893.  
  894.     if (info->isEuclidean == TRUE) {
  895.       c << ibloc << "\nIs a Euclidean space\n";
  896.       c << ibloc << "Standard inner product:\n";
  897.       info->innerProd.debug_out(c, indent + ERR_IND);
  898.       c << ibloc << "Standard cross product:\n";
  899.       info->crossProd.debug_out(c, indent + ERR_IND);
  900.     } else {
  901.       c << ibloc << "\nIs not a Euclidean space\n";
  902.     }
  903.  
  904.     c << ibloc << "Set of points at infinity:\n";
  905.     info->atInfinity.debug_out(c, indent + ERR_IND);
  906.  
  907.     c << ibloc << "Tangent vector hoisting matrix:\n";
  908.     info->hoistTangent.debug_out(c, indent + ERR_IND);
  909.  
  910.     c << ibloc << "Standard affine subset:\n";
  911.     info->stdAffineSet.debug_out(c, indent + ERR_IND);
  912.  
  913.     c << ibloc << "Full space subset:\n";
  914.     info->fullset.debug_out(c, indent + ERR_IND);
  915.  
  916.     c << ibloc << "Full space projective subset:\n";
  917.     info->fullproj.debug_out(c, indent + ERR_IND);
  918.   }
  919.   c << ibloc << ast;
  920.  
  921.   delete ibloc;
  922.   return;
  923. }
  924. // ***********************************************************************
  925.  
  926.  
  927. // ***********************************************************************
  928. //
  929. // Public member functions
  930. //
  931. // ***********************************************************************
  932.  
  933. Space::Space(void) {type = ANY_SPACE; holds = NULL_SPACE; info = &errinfo;}
  934.  
  935. // ***********************************************************************
  936. // 
  937. // Do memberwise initialization.  Since no class members need to be
  938. // copied, this constructor should not be necessary.  However,
  939. // it seems to be necessary to define this to suppress a wierd compiler
  940. // error.
  941. //
  942.  
  943. Space::Space(Space& v) {type = ANY_SPACE; holds = v.holds; info = v.info;}
  944.  
  945. // ***********************************************************************
  946. //
  947. // Do memberwise assignment.  (Needed to catch g++ 1.37 bug).
  948. //
  949.  
  950. Space& Space::operator=(Space &s)
  951. {
  952. //
  953. // This weird checking is required to bypass the apparent inheritance of
  954. // assignment under g++ 1.37:
  955. //
  956.   if ((type != ANY_SPACE) &&
  957.       ((type != s.holds) && (s.holds != NULL_SPACE))) {
  958.     errh.ErrorExit("Space& Space::operator=(Space &)",
  959.                    "Illegal assignment attempted", *this, s);
  960.   }
  961.   holds = s.holds;
  962.   info = s.info;
  963.   return (*this);
  964. }
  965.  
  966. // ***********************************************************************
  967. //
  968. // More perfect candidates for inlining, but see the above remark:
  969. //
  970. // ***********************************************************************
  971.  
  972. int Space::Dim(void) {return (info->dim);}
  973.  
  974. // ***********************************************************************
  975.  
  976. char* Space::Name(char *buf) {return (strcpy(buf, info->name));}
  977.  
  978. // ***********************************************************************
  979.  
  980. Basis Space::StdBasis(void) {return (info->stdBasis);}
  981.  
  982. // ***********************************************************************
  983.  
  984. Simplex Space::StdSimplex(void) {return (Simplex(info->stdBasis));}
  985.  
  986. // ***********************************************************************
  987.  
  988. int Space::CPSpaceSize(void) {return (info->cpSize);}
  989.  
  990. // ***********************************************************************
  991.  
  992. SRel Space::ThisSpaceIs(void) {return (info->thisSpace);}
  993.  
  994. // ***********************************************************************
  995.  
  996. SubSet Space::FullSet(void) {return info->fullset;}
  997.  
  998. // ***********************************************************************
  999.  
  1000. GeObType Space::NativeType(void) {return (info->native);}
  1001.  
  1002. // ***********************************************************************
  1003. //
  1004. // The following three functions are not inlined to avoid bitwise copying
  1005. // under CFRONT 1.2:
  1006. //
  1007.  
  1008. AffineMap Space::AffineMapTo(SRel s) {return (this->AffineMapToRef(s));}
  1009.  
  1010. // ***********************************************************************
  1011.  
  1012. ProjectiveMap Space::ProjectiveMapTo(SRel s)
  1013.   {return (this->ProjectiveMapToRef(s));}
  1014.  
  1015. // ***********************************************************************
  1016.  
  1017. LinearMap Space::LinearMapTo(SRel s) {return(this->LinearMapToRef(s));}
  1018.  
  1019. // ***********************************************************************
  1020.  
  1021. Boolean Space::IsEuclidean(void)
  1022. {
  1023.   if ((holds != VEC_SPACE) && (holds != AFF_SPACE)) {
  1024.     errh.ErrorExit("Boolean Space::IsEuclidean(void)",
  1025.            "Space is not vector or affine", *this);
  1026.   }
  1027.   return (info->isEuclidean);
  1028. }
  1029.  
  1030. // ***********************************************************************
  1031.  
  1032. GeObList Space::PtsAtInfinity(void)
  1033. {
  1034.   if (holds != PROJ_SPACE) {
  1035.     errh.ErrorExit("GeObList Space::PtsAtInfinity(void)",
  1036.            "Space is not projective", *this);
  1037.   }
  1038.   return (info->atInfinity);
  1039. }
  1040.  
  1041. // ***********************************************************************
  1042.  
  1043. PSubSet Space::FullProjSet(void)
  1044. {
  1045.   if ((holds != VEC_SPACE) && (holds != PROJ_SPACE)) {
  1046.     errh.ErrorExit("SubSet Space::FullProjSet(void)",
  1047.            "Space is not vector or projective", *this);
  1048.   }
  1049.   return (info->fullproj);
  1050. }
  1051.  
  1052. // ***********************************************************************
  1053. // 
  1054. // This is a "short form" debug output for a Space.  It is the form
  1055. // that will be called by all other objects that contain a space, and
  1056. // will not cause infinite recursion of printouts.  Use the extended
  1057. // form to get a full dump of the space data.  
  1058. //
  1059.  
  1060. void Space::debug_out(ostream &c, int indent)
  1061. {
  1062.   static char *name = "Space object\n";
  1063.   this->data_out(c, indent, name);
  1064.   return;
  1065. }
  1066.  
  1067. // ***********************************************************************
  1068. // 
  1069. // This debug output dumps ALL the data in the space.  It should not be 
  1070. // be called by the debug output functions of any class that has a 
  1071. // member in space, or infinite recursion will result.  
  1072. //
  1073.  
  1074. void Space::heavy_debug_out(ostream &c, int indent) 
  1075. {
  1076.   static char *name = "Full data dump for a space\n";
  1077.   this->heavy_data_out(c, indent, name);
  1078.   return;
  1079. }
  1080.  
  1081.  
  1082. // ***********************************************************************
  1083. // 
  1084. // Given a space, this function returns the SRel indicating how the
  1085. // argument is related to this space:
  1086. //
  1087.  
  1088. SRel Space::SpaceRelation(Space &s)
  1089. {
  1090.   if (s == *this) {
  1091.     return (SAME_SPACE);
  1092.   } else {
  1093.     for (int i = 0; i < SP_SET_SIZE; i++) {
  1094.       if (info->spaceSet[i] == s) {
  1095.     return (SRel)i;
  1096.       }
  1097.     }
  1098.     return (NO_RELATION);
  1099.   }
  1100. }
  1101.  
  1102. // ***********************************************************************
  1103. // 
  1104. // Check to see if the related space has been specified, without 
  1105. // creating it if it has not:
  1106. //
  1107.  
  1108. Boolean Space::HasSpace(SRel s)
  1109. {
  1110.   if (s >= (int)NO_RELATION) {
  1111.     errh.ErrorExit("Boolean Space::HasSpace(SRel)",
  1112.                    "Invalid relation specified",
  1113.             ErrType("Space relation specified =", s, SRELTYPES));
  1114.   }
  1115.  
  1116. // Look in the slot.  If the space we find is not a null space, it has
  1117. // been specified, so return TRUE.
  1118.  
  1119.   return ((info->spaceSet[s]).Holds() != NULL_SPACE);
  1120. }
  1121.  
  1122. // ***********************************************************************
  1123. // 
  1124. // Get the space in the specified slot.  If no space of the specified
  1125. // relation exists, this routine creates it.
  1126. //
  1127.  
  1128. Space Space::GetSpace(SRel s)
  1129. {
  1130.   static char* sig = "Space Space::GetSpace(SRel)";
  1131.   Space retval;
  1132.   Space holdsp;
  1133.   Boolean eflag;
  1134.   char* tag;
  1135.  
  1136.   if (s >= (int)NO_RELATION) {
  1137.     errh.ErrorExit(sig, "Invalid relation specified",
  1138.            ErrType("Space relation specified =", s, SRELTYPES));
  1139.   }
  1140.  
  1141. // Look in the slot.  If the space we find is a null space, it has not
  1142. // been created, so build it.
  1143.  
  1144.   if ((info->spaceSet[s]).Holds() != NULL_SPACE) {
  1145.     return (info->spaceSet[s]);
  1146.   } else {
  1147.     switch (s) {
  1148.       case TANGENT:
  1149.       case LIN_DUAL: 
  1150.       case TANG_DUAL: 
  1151.     retval = VSpace(s, *this); 
  1152.         break;
  1153.       case LINEARIZATION: 
  1154.     if (this->HasSpace(AFFINE)) {
  1155.       holdsp = this->GetSpace(AFFINE);
  1156.       eflag = holdsp.IsEuclidean();
  1157.     } else {
  1158.       holdsp = this->GetSpace(PROJECT_COMP);
  1159.       eflag = TRUE;
  1160.     }
  1161.     tag = this->BuildTagName("Linearization for ", holdsp);
  1162.     retval = VSpace(tag, eflag, holdsp);
  1163.     this->DestroyTagName(tag);
  1164.         break;
  1165.       case PROJECT_COMP:
  1166.     if (this->HasSpace(AFFINE)) {
  1167.       holdsp = this->GetSpace(AFFINE);
  1168.     } else {
  1169.       holdsp = this->GetSpace(LINEARIZATION);
  1170.     }
  1171.     tag = this->BuildTagName("Proj. Space for ", holdsp);
  1172.     retval = PSpace(tag, holdsp);
  1173.     this->DestroyTagName(tag);
  1174.         break;
  1175.       case AFFINE: 
  1176.     if (this->HasSpace(LINEARIZATION)) {
  1177.       holdsp = this->GetSpace(LINEARIZATION);
  1178.       eflag = holdsp.IsEuclidean();
  1179.     } else {
  1180.       holdsp = this->GetSpace(PROJECT_COMP);
  1181.       eflag = TRUE;
  1182.     }
  1183.     tag = this->BuildTagName("Affine Space for ", holdsp);
  1184.     retval = ASpace(tag, eflag, holdsp);
  1185.     this->DestroyTagName(tag);
  1186.         break;
  1187.       case NO_RELATION:
  1188.       case SAME_SPACE:
  1189.       default:
  1190.         errh.ErrorExit(sig, "Invalid relation specified",
  1191.                ErrType("Space relation specified =", s, SRELTYPES));
  1192.         break;
  1193.       }
  1194.   }
  1195.   return (retval);
  1196. }
  1197.  
  1198. // ***********************************************************************
  1199. // 
  1200. // Used to stitch spaces together manually.
  1201. //
  1202.  
  1203. Space Space::SetSpace(Space& s, Map& m)
  1204. {
  1205.   static char* sig = "Space Space::SetSpace(Space&, Map&)";
  1206.   Space rv;
  1207.  
  1208. // Dispatch to different routines depending on what type of space
  1209. // this is:
  1210.  
  1211.   switch (holds) {
  1212.     case VEC_SPACE:
  1213.       rv = VSpace(*this).SetSpace(s, m);
  1214.       break;
  1215.     case AFF_SPACE:
  1216.       rv = ASpace(*this).SetSpace(s, m);
  1217.       break;
  1218.     case PROJ_SPACE:
  1219.       rv = PSpace(*this).SetSpace(s, m);
  1220.       break;
  1221.     case NULL_SPACE:
  1222.     case ANY_SPACE:
  1223.     default:
  1224.       errh.ErrorExit(sig, "Illegal space type",
  1225.                  ErrType("Type specified =", holds, SPACETYPES), *this);
  1226.       break;
  1227.   }
  1228.   return (rv);
  1229. }
  1230.  
  1231. // ***********************************************************************
  1232. //
  1233. // Returns the dual space
  1234. //
  1235.  
  1236. VSpace Space::Dual(void) 
  1237. {
  1238.   SRel rel;
  1239.  
  1240. // Again, lazy space creation is an issue.
  1241.  
  1242.   if ((info->dual).Holds() != NULL_SPACE) {
  1243.     return (info->dual);
  1244.   } else if (info->thisSpace == LINEARIZATION) {
  1245.     rel = LIN_DUAL;
  1246.   } else if (info->thisSpace == TANGENT) {
  1247.     rel = TANG_DUAL;
  1248.   } else {
  1249.     errh.ErrorExit("VSpace Space::Dual(void)",
  1250.                    "Space cannot have a dual", *this);
  1251.   }
  1252.   info->dual = VSpace(rel, *this);
  1253.   return (info->dual);
  1254. }
  1255.  
  1256. // ***********************************************************************
  1257. // 
  1258. // Inner products are created lazily:
  1259. //
  1260.  
  1261. MLM Space::InnerProduct(void)
  1262. {
  1263.   static char* sig = "MLM Space::InnerProduct(void)";
  1264.  
  1265.   if (holds != VEC_SPACE) {
  1266.     errh.ErrorExit(sig, "Must be a vector space", *this);
  1267.   }
  1268.   if (!info->isEuclidean) {
  1269.     errh.ErrorExit(sig, "Must be a Euclidean space", *this);
  1270.   }
  1271.  
  1272.   if (info->innerProd.Holds() == NULL_MULTI) {
  1273.     info->innerProd = MLM(INNER_PROD, *this);
  1274.   }
  1275.   return (info->innerProd);
  1276. }
  1277.  
  1278. // ***********************************************************************
  1279. // 
  1280. // Cross products are created lazily:
  1281. //
  1282.  
  1283. MLM Space::CrossProduct(void)
  1284. {
  1285.   static char* sig = "MLM Space::CrossProduct(void)";
  1286.  
  1287.   if (holds != VEC_SPACE) {
  1288.     errh.ErrorExit(sig, "Must be a vector space", *this);
  1289.   }
  1290.   if (!info->isEuclidean) {
  1291.     errh.ErrorExit(sig, "Must be a Euclidean space", *this);
  1292.   }
  1293.  
  1294.   if (info->crossProd.Holds() == NULL_MULTI) {
  1295.     info->crossProd = MLM(CROSS_PROD, *this);
  1296.   }
  1297.   return (info->crossProd);
  1298. }
  1299.  
  1300. // ***********************************************************************
  1301. // 
  1302. // Only Spaces that have been linked to an affine space have a standard
  1303. // affine subset.
  1304. //
  1305.  
  1306. ASubSet Space::StdAffineSubset(void) 
  1307. {
  1308.   ASubSet retval;
  1309.  
  1310.   static char* sig = "ASubSet Space::StdAffineSubset(void)";
  1311.   switch (info->thisSpace) {
  1312.     case LINEARIZATION:
  1313.     case PROJECT_COMP: 
  1314.       this->GetSpace(AFFINE); // make sure space exists first
  1315.       retval = info->stdAffineSet;
  1316.       break;
  1317.     case AFFINE: 
  1318.       retval = info->stdAffineSet;
  1319.       break;
  1320.     case TANGENT:
  1321.     case LIN_DUAL: 
  1322.     case TANG_DUAL: 
  1323.       errh.ErrorExit(sig,
  1324.              "Space does not have a standard affine subset", *this);
  1325.       break;
  1326.     case NO_RELATION:
  1327.     case SAME_SPACE:
  1328.     default:
  1329.       errh.ErrorExit(sig, "Unexpected relation",
  1330.              ErrType("Space relation found =",
  1331.                  info->thisSpace, SRELTYPES));
  1332.       break;
  1333.   }
  1334.   return (retval);
  1335. }
  1336.  
  1337.  
  1338. // ***********************************************************************
  1339.  
  1340. Space Space::operator[](int n)
  1341. {
  1342.   if ((n < 0) || (n >= info->cpSize)) {
  1343.     errh.ErrorExit("Space Space::operator[](int)",
  1344.                    "n is out of range",
  1345.            ErrVal("n = ", n), *this);
  1346.   }
  1347.   if (info->cpSize == 1) {
  1348.     return *this;
  1349.   } else {
  1350.     return(info->cpSpaces[n]);
  1351.   }
  1352. }
  1353.  
  1354. // ***********************************************************************
  1355. // ***********************************************************************
  1356. // 
  1357. // VSpace Class 
  1358. // 
  1359. // ***********************************************************************
  1360. // ***********************************************************************
  1361. //
  1362. // Private/protected member functions
  1363. //
  1364. // ***********************************************************************
  1365. // 
  1366. // This private method is responsible for system-built dual and tangent
  1367. // spaces.
  1368.  
  1369. VSpace::VSpace(SRel s, Space& ins) 
  1370. {
  1371.   Space temp;
  1372.   GeObType nativetype;
  1373.   SRel access;
  1374.   Boolean useDual;
  1375.   char* tag;
  1376.  
  1377. // Catch the case where we are trying to build the dual of the Real
  1378. // Space, which is self-dual!  All other spaces Rn are distinct
  1379. // fom their dual spaces.
  1380.  
  1381.   if (s == LIN_DUAL) {
  1382.     temp = ins.GetSpace(LINEARIZATION);
  1383.     if (temp == Reals) {
  1384.       temp.SetDual(temp);
  1385.       temp.SetSpaceSet(LIN_DUAL, temp);
  1386.       temp.MergeSets(ins);
  1387.       return;
  1388.     }
  1389.   }
  1390.  
  1391. // Handle the regular cases.  Allocate a new SpaceInfo:
  1392.  
  1393.   info = new SpaceInfo;
  1394.   type = VEC_SPACE;
  1395.   holds = VEC_SPACE;
  1396.  
  1397. // Some stuff depends on what kind of space we are building:
  1398.  
  1399.   if (s == LIN_DUAL) {
  1400.     useDual = TRUE;
  1401.     access = LINEARIZATION;
  1402.   } else if (s == TANG_DUAL) {
  1403.     useDual = TRUE;
  1404.     access = TANGENT;
  1405.   } else if (s == TANGENT) {
  1406.     useDual = FALSE;
  1407.     access = AFFINE;
  1408.   } else {
  1409.     errh.ErrorExit("VSpace::VSpace(SRel, Space&)", "Unexpected relation",
  1410.            ErrType("Space relation found =", s, SRELTYPES));
  1411.   }
  1412.  
  1413.   temp = ins.GetSpace(access);
  1414.  
  1415.   if (useDual) {
  1416.     tag = this->BuildTagName("Dual to ", temp);
  1417.     nativetype = VECTOR;
  1418.     info->dual = temp;
  1419.   } else {
  1420.     tag = this->BuildTagName("Tangent to ", temp);
  1421.     nativetype = AFF_VECTOR;
  1422.   }
  1423.  
  1424.   this->CopyDebugName(tag);
  1425.   this->DestroyTagName(tag);
  1426.  
  1427. // Start to fill in all the information:
  1428.  
  1429.   info->type = VEC_SPACE;
  1430.   info->dim = temp.Dim();
  1431.   info->matsize = info->dim;
  1432.   info->native = nativetype;
  1433.   info->thisSpace = s;
  1434.   info->spaceSet[(int)s] = *this;
  1435.   info->stdBasis = Basis(VBASIS, *this, info->dim);
  1436.   info->isEuclidean = temp.IsEuclidean();
  1437.  
  1438. // If the given space is a CPSpace of spaces, this space should be
  1439. // a CPSpace of spaces, either the tangents or duals:
  1440.  
  1441.   info->cpSize = temp.CPSpaceSize();
  1442.   int dim_sum = 0;
  1443.  
  1444.   if (info->cpSize > 1) {
  1445.     info->cpSpaces = SpaceList(info->cpSize);
  1446.     info->cpSlots = IntList(info->cpSize);
  1447.     for (int j = 0; j < info->cpSize; j++) {   
  1448.       if (useDual) {
  1449.         (info->cpSpaces)[j] = (temp[j]).Dual();
  1450.       } else {
  1451.         (info->cpSpaces)[j] = (temp[j]).GetSpace(TANGENT);
  1452.       }
  1453.       (info->cpSlots)[j] = dim_sum;
  1454.       dim_sum += (info->cpSpaces)[j].Dim();
  1455.     }
  1456.   } else {
  1457.     info->cpSlots = IntList(1);
  1458.   }
  1459.  
  1460. // Broadcast the space:
  1461.  
  1462.   this->Broadcast(s, ins);
  1463.  
  1464. // Build standard subsets:
  1465.  
  1466.   info->fullset = VSubSet(*this);
  1467.   info->fullproj = PSubSet(*this);
  1468.  
  1469. // Clean-up work (announcing dual or installing standard maps):
  1470.  
  1471.   if (useDual) {
  1472.     temp.SetDual(*this);
  1473.   } else {
  1474.     if (this->HasSpace(LINEARIZATION)) {
  1475.       this->LinkLT();
  1476.     }
  1477.   }
  1478. }
  1479.  
  1480. // ***********************************************************************
  1481. //
  1482. // Public member functions
  1483. //
  1484. // ***********************************************************************
  1485. //
  1486. // Used to cast a general space down to a vector space.
  1487. //
  1488.  
  1489. VSpace::VSpace(Space& s) : (s)
  1490. {
  1491.   type = VEC_SPACE;
  1492.   if ((holds != VEC_SPACE) && (holds != NULL_SPACE))  {
  1493.       errh.ErrorExit("VSpace::VSpace(Space&)",
  1494.                      "Attempted to cast a non-vector space to a vector space",
  1495.              s);
  1496.   }
  1497. }
  1498.  
  1499. // ***********************************************************************
  1500. //
  1501. // Memberwise assignment:
  1502. //
  1503.  
  1504. VSpace& VSpace::operator=(VSpace &s)
  1505. {
  1506.   holds = s.holds;
  1507.   info = s.info;
  1508.   return (*this);
  1509. }
  1510.  
  1511. // ***********************************************************************
  1512. //
  1513. // Output for debugging
  1514. //
  1515.  
  1516. void VSpace::debug_out(ostream &c, int indent)
  1517. {
  1518.   static char* name = "VSpace Object\n";
  1519.   this->data_out(c, indent, name);
  1520.   return;
  1521. }
  1522.  
  1523. // ***********************************************************************
  1524. // 
  1525. // Stitches the given space into this space (which is a linearization) using
  1526. // the user specified map:
  1527. //
  1528.  
  1529. Space VSpace::SetSpace(Space& ins, Map& m)
  1530. {
  1531.   static char* sig = "Space VSpace::SetSpace(Space&, Map&)";
  1532.  
  1533. // Start by enforcing restrictions on the spaces.
  1534.  
  1535.   if (this->ThisSpaceIs() != LINEARIZATION) {
  1536.       errh.ErrorExit(sig,
  1537.                      "Only linearization spaces can be stitched manually",
  1538.              *this);
  1539.   }
  1540.   
  1541.   SRel rel = ins.ThisSpaceIs();
  1542.  
  1543.   if ((rel != AFFINE) && (rel != PROJECT_COMP)) {
  1544.     errh.ErrorExit(sig, "Incorrect type of space specified", ins);
  1545.   }
  1546.  
  1547. // The specified space must be unattached to another linear space, and
  1548. // we must be unattached:
  1549.  
  1550.   if (ins.HasSpace(LINEARIZATION)) {
  1551.     errh.ErrorExit(sig, "Specified space already linked", ins);
  1552.   }
  1553.  
  1554.   if (this->HasSpace(rel)) {
  1555.     errh.ErrorExit(sig, "This space already linked", *this);
  1556.   }
  1557.  
  1558. // Dimensionality must match:
  1559.  
  1560.   if (this->Dim() != ins.Dim() + 1) {
  1561.     errh.ErrorExit(sig, "Dimensions do not match", ins, *this);
  1562.   }
  1563.  
  1564. // If the other link of one is filled, the same link must be unfilled
  1565. // on the other.  We are taking advantage here of the fact that this
  1566. // space has not yet been registered with others in the set:
  1567.  
  1568.   if ((ins.HasSpace(AFFINE)) && (this->HasSpace(AFFINE))) {
  1569.     errh.ErrorExit(sig, "Linked to mismatched affine spaces", ins, *this);
  1570.   }  
  1571.   if ((ins.HasSpace(PROJECT_COMP)) && (this->HasSpace(PROJECT_COMP))) {
  1572.     errh.ErrorExit(sig, "Linked to mismatched proj. completions", ins, *this);
  1573.   }  
  1574.  
  1575. // Now check that the map we have been given fits the bill for stitching
  1576. // two spaces together.  If the given space is affine, the map must be
  1577. // affine; if projective, the map must be projective:
  1578.  
  1579.   if ((rel == AFFINE) && (m.Holds() != AFF_MAP)) {
  1580.     errh.ErrorExit(sig, "Map must be affine", ins, *this, m);
  1581.   }
  1582.  
  1583.   if ((rel == PROJECT_COMP) && (m.Holds() != PROJ_MAP)) {
  1584.     errh.ErrorExit(sig, "Map must be projective", ins, *this, m);
  1585.   }
  1586.  
  1587. // The range and domain must match the spaces we have:
  1588.  
  1589.   SubSet Rsub = m.Range();
  1590.   SubSet Dsub = m.Domain();
  1591.   Space Remb = Rsub.EmbeddingSpace();
  1592.   Space Demb = Dsub.EmbeddingSpace();
  1593.  
  1594.   if ((Remb != ins) || (!Rsub.IsFullSpace())) {
  1595.     errh.ErrorExit(sig, "Map Range/Dimension mismatch", ins, *this, m);
  1596.   }
  1597.   if ((rel == AFFINE) &&
  1598.       ((Demb != *this) || (Dsub.Dim() != ins.Dim()))) {
  1599.     errh.ErrorExit(sig, "Map Domain/Dimension mismatch", ins, *this, m);
  1600.   }
  1601.   if ((rel == PROJECT_COMP) &&
  1602.       ((Demb != *this) || (Dsub.Dim() != ins.Dim() + 1))) {
  1603.     errh.ErrorExit(sig, "Map Domain/Dimension mismatch", ins, *this, m);
  1604.   }
  1605.  
  1606. // Install the standard linkage maps.  Do the set merging only after
  1607. // we have checked the state of the original sets for choosing:
  1608.  
  1609.   if (rel == AFFINE) {
  1610.     if (this->HasSpace(PROJECT_COMP)) {
  1611.       this->MergeSets(ins);
  1612.       this->LinkLAHaveLP(m);
  1613.     } else if (ins.HasSpace(PROJECT_COMP)) {
  1614.       this->MergeSets(ins);
  1615.       this->LinkLAHaveAP(m);
  1616.     } else {
  1617.       this->MergeSets(ins);
  1618.       this->LinkLA(m);
  1619.     }
  1620.   } else {  // rel == PC
  1621.     if (this->HasSpace(AFFINE)) {
  1622.       this->MergeSets(ins);
  1623.       this->LinkLPHaveLA(m);
  1624.     } else if (ins.HasSpace(AFFINE)) {
  1625.       this->MergeSets(ins);
  1626.       this->LinkLPHaveAP(m);
  1627.     } else {
  1628.       this->MergeSets(ins);
  1629.       this->LinkLP(m);
  1630.     }
  1631.   }
  1632.   return (*this);
  1633. }
  1634.  
  1635. // ***********************************************************************
  1636. // 
  1637. // Construct a plain vanilla Vector space, with no attachments to
  1638. // other spaces: 
  1639. //
  1640.  
  1641. VSpace::VSpace(char* namein, int n, Boolean eflag) 
  1642. {
  1643.   static char* sig = "VSpace::VSpace(char*, int, Boolean)";
  1644.  
  1645.   if (n < 1) {
  1646.     errh.ErrorExit(sig, "Dimension is out of range", ErrVal("Dim = ", n));
  1647.   }
  1648.  
  1649. // Create a new SpaceInfo:
  1650.  
  1651.   info = new SpaceInfo;
  1652.   type = VEC_SPACE;
  1653.   holds = VEC_SPACE;
  1654.  
  1655. // Fill in all the pertinent information:
  1656.  
  1657.   info->type = type;
  1658.   info->dim = n;
  1659.   info->matsize = info->dim;
  1660.   info->native = VECTOR;
  1661.   info->cpSize = 1;
  1662.   info->cpSlots = IntList(1);
  1663.   info->thisSpace = LINEARIZATION;
  1664.   info->stdBasis = Basis(VBASIS, *this, n);
  1665.   info->isEuclidean = eflag;
  1666.   this->CopyDebugName(namein);
  1667.   
  1668. // Fill in this slot of the space set:
  1669.  
  1670.   info->spaceSet[LINEARIZATION] = *this;
  1671.  
  1672. // Build standard subsets:
  1673.  
  1674.   info->fullset = VSubSet(*this);
  1675.   info->fullproj = PSubSet(*this);
  1676. }
  1677.  
  1678. // ***********************************************************************
  1679. // 
  1680. // Build a vector space that is attached to specified affine and 
  1681. // projective spaces.  Stitch them together with standard maps:
  1682. //
  1683.  
  1684. VSpace::VSpace(char* namein, Boolean eflag, ASpace& a, PSpace& p) 
  1685. {
  1686.   static char* sig = "VSpace::VSpace(char*, Boolean, ASpace&, PSpace&)";
  1687.  
  1688.   type = VEC_SPACE;
  1689.  
  1690. // Make sure that the various spaces specified have the correct dimension:
  1691.  
  1692.   if (a.Dim() != p.Dim()) {
  1693.     errh.ErrorExit(sig, "Mismatch of dimensions", a, p);
  1694.   }
  1695.  
  1696. // The specified spaces must be unattached to linearizations:
  1697.  
  1698.   if (a.HasSpace(LINEARIZATION) || p.HasSpace(LINEARIZATION)) {
  1699.     errh.ErrorExit(sig, "One or more specified spaces already linked", a, p);
  1700.   }
  1701.  
  1702. // Start by constructing an unattached vector space:
  1703.  
  1704.   *this = VSpace(namein, a.Dim() + 1, eflag); 
  1705.  
  1706. // Figure out if the specified spaces are unlinked or linked to each other,
  1707. // then link them if necessary:
  1708.  
  1709.   Boolean linkerr;
  1710.   Boolean linked = this->HaveLink(a, AFFINE, p, PROJECT_COMP, &linkerr);
  1711.  
  1712.   if (linkerr) {
  1713.     errh.ErrorExit(sig, "Spaces must be unlinked or linked to each other",
  1714.            a, p);
  1715.   }
  1716.  
  1717.   if (!linked) {
  1718.     p.MergeSets(a);
  1719.     p.LinkAP(AffineMap(a, p));
  1720.   }
  1721.  
  1722. // Broadcast the space:
  1723.  
  1724.   this->Broadcast(LINEARIZATION, a);
  1725.  
  1726. // Install the standard maps:
  1727.  
  1728.   LinkLAHaveAP(AffineMap(*this, a));
  1729. }
  1730.  
  1731. // ***********************************************************************
  1732. // 
  1733. // Build a vector space that is attached to the specified space, which
  1734. // must be either affine or projective.  Stitch them together with
  1735. // standard maps:
  1736. //
  1737.  
  1738. VSpace::VSpace(char* namein, Boolean eflag, Space& ins) 
  1739. {
  1740.   static char* sig = "VSpace::VSpace(char*, Boolean, Space&)";
  1741.  
  1742.   type = VEC_SPACE;
  1743.  
  1744. // The specified space must be the right kind:
  1745.   
  1746.   SRel rel = ins.ThisSpaceIs();
  1747.  
  1748.   if ((rel != AFFINE) && (rel != PROJECT_COMP)) {
  1749.     errh.ErrorExit(sig, "Incorrect type of space specified", ins);
  1750.   }
  1751.  
  1752. // The specified space must be unattached to another linearization:
  1753.  
  1754.   if (ins.HasSpace(LINEARIZATION)) {
  1755.     errh.ErrorExit(sig, "Specified space already linked", ins);
  1756.   }
  1757.  
  1758. // Start by constructing an unattached vector space:
  1759.  
  1760.   *this = VSpace(namein, ins.Dim() + 1, eflag); 
  1761.  
  1762. // Broadcast the space:
  1763.  
  1764.   this->Broadcast(LINEARIZATION, ins);
  1765.  
  1766. // Install the standard maps:
  1767.  
  1768.   if (rel == AFFINE) {
  1769.     if (ins.HasSpace(PROJECT_COMP)) {
  1770.       LinkLAHaveAP(AffineMap(*this, ins));
  1771.     } else {
  1772.       LinkLA(AffineMap(*this, ins));
  1773.     }
  1774.   } else { // rel = PROJECT_COMP
  1775.     if (ins.HasSpace(AFFINE)) {
  1776.       LinkLAHaveAP(AffineMap(*this, ins.GetSpace(AFFINE)));
  1777.     } else {
  1778.       LinkLP(ProjectiveMap(*this, ins));
  1779.     }
  1780.   }
  1781. }
  1782.  
  1783. // ***********************************************************************
  1784. //
  1785. // This constructor is used to build Cartesian Product spaces from
  1786. // a list of existing spaces.  The space that results is a bare space;
  1787. // no other spaces are linked to it.
  1788. //
  1789.  
  1790. VSpace::VSpace(char* namein, SpaceList& t, Boolean eflag)
  1791. {
  1792.   static char* sig = "VSpace::VSpace(char*, SpaceList&, Boolean)"; 
  1793.   int i;
  1794.  
  1795. // Error if no spaces in the list, or if there is only one space
  1796. // in the list (cannot create aliases for atomic spaces):
  1797.  
  1798.   if (t.Length() <= 1) {
  1799.     errh.ErrorExit(sig, "Not enough spaces in space list", t);
  1800.   }
  1801.  
  1802. // Crete a new SpaceInfo:
  1803.  
  1804.   info = new SpaceInfo;
  1805.   type = VEC_SPACE;
  1806.   holds = VEC_SPACE;
  1807.  
  1808. // All the spaces in the list must be vector spaces.  The dimension
  1809. // of this space is the sum of the dimensions of the spaces in the
  1810. // list.  The cardinality of this space is the sum of the 
  1811. // cardinalities of the spaces in the list (spaces in the list
  1812. // may themselves be CPSpaces).  A problem with this system (which
  1813. // lacks global knowledge of CP spaces in the system is that the
  1814. // user (and the system) can currently create aliases of certain
  1815. // special system-built CP spaces (the tangent and dual spaces
  1816. // of CPSpaces).  These aliases will always sit as linearization
  1817. // spaces in a six-space set.
  1818.  
  1819.   info->dim = 0;
  1820.   info->cpSize = 0;
  1821.   
  1822.   for (i = 0; i < t.Length(); i++) {
  1823.     Space temp = t[i];
  1824.     if (temp.Holds() != VEC_SPACE) {
  1825.       errh.ErrorExit(sig, "Non-vector space in space list", t);
  1826.     }
  1827.     info->dim += temp.Dim();
  1828.     info->cpSize += temp.CPSpaceSize();
  1829.   }
  1830.  
  1831. // Build the necessary lists and go through the space list once more,
  1832. // filling in as we go:
  1833.  
  1834.   info->cpSpaces = SpaceList(info->cpSize);
  1835.   info->cpSlots = IntList(info->cpSize);
  1836.   int slot = 0;
  1837.   int dim_sum = 0;
  1838.  
  1839.   for (i = 0; i < t.Length(); i++) {
  1840.     Space temp = t[i];
  1841.     for (int j = 0; j < temp.CPSpaceSize(); j++) {   
  1842.       (info->cpSpaces)[slot] = temp[j];
  1843.       (info->cpSlots)[slot++] = dim_sum;
  1844.       dim_sum += (temp[j]).Dim();
  1845.     }
  1846.   }  
  1847.  
  1848. // This is a bare vector space:
  1849.  
  1850.   info->type = type;
  1851.   info->matsize = info->dim;
  1852.   info->native = VECTOR;
  1853.   info->thisSpace = LINEARIZATION;
  1854.   info->stdBasis = Basis(VBASIS, *this, info->dim);
  1855.   info->spaceSet[LINEARIZATION] = *this;
  1856.   info->isEuclidean = eflag;
  1857.   this->CopyDebugName(namein);
  1858.  
  1859. // Build standard subsets:
  1860.  
  1861.   info->fullset = VSubSet(*this);
  1862.   info->fullproj = PSubSet(*this);
  1863.  
  1864. }
  1865.  
  1866. // ***********************************************************************
  1867. // ***********************************************************************
  1868. //
  1869. // ASpace Class
  1870. //
  1871. // ***********************************************************************
  1872. // ***********************************************************************
  1873. // ***********************************************************************
  1874. //
  1875. // Private/protected member functions
  1876. //
  1877. // ***********************************************************************
  1878. //
  1879. // Private method used by ASpaces to build their hoist matrices:
  1880. //
  1881.  
  1882. Matrix ASpace::BuildHoist(int n)
  1883. {
  1884. // The hoist matrix converts the matrix rep. of vectors in the tangent
  1885. // space to the matrix rep. in the affine space.  It is just an
  1886. // identity matrix with an extra column of zeros.
  1887.  
  1888.   Matrix retval = ZeroMatrix(n, n + 1);
  1889.   for (int i = 0; i < n; i++) {
  1890.     retval[i][i] = 1.0;
  1891.   } 
  1892.   return (retval);
  1893. }
  1894.  
  1895. // ***********************************************************************
  1896. //
  1897. // Public member functions
  1898. //
  1899. // ***********************************************************************
  1900. //
  1901. // Downcasts a general space to an affine space (if it is one):
  1902.  
  1903. ASpace::ASpace(Space& s) : (s)
  1904. {
  1905.   type = AFF_SPACE;
  1906.   if ((holds != AFF_SPACE) && (holds != NULL_SPACE)) {
  1907.       errh.ErrorExit("ASpace::ASpace(Space&)",
  1908.                      "Attempted to cast a non-affine space to an affine space",
  1909.              s);
  1910.   }
  1911. }
  1912.  
  1913. // ***********************************************************************
  1914. //
  1915. // Assignment
  1916. //
  1917.  
  1918. ASpace& ASpace::operator=(ASpace &s)
  1919. {
  1920.   holds = s.holds;
  1921.   info = s.info;
  1922.   return (*this);
  1923. }
  1924.  
  1925. // ***********************************************************************
  1926. //
  1927. // Output for debugging:
  1928. //
  1929.  
  1930. void ASpace::debug_out(ostream &c, int indent)
  1931. {
  1932.   static char *name = "ASpace Object\n";
  1933.   this->data_out(c, indent, name);
  1934.   return;
  1935. }
  1936.  
  1937. // ***********************************************************************
  1938. // 
  1939. // Stitches the given space to this space (which is affine) using
  1940. // the user specified map:
  1941. //
  1942.  
  1943. Space ASpace::SetSpace(Space& ins, Map& m)
  1944. {
  1945.   static char* sig = "Space ASpace::SetSpace(Space&, Map&)";
  1946.  
  1947. // Start by enforcing restrictions on the spaces.
  1948.   
  1949.   SRel rel = ins.ThisSpaceIs();
  1950.  
  1951.   if ((rel != LINEARIZATION) && (rel != PROJECT_COMP)) {
  1952.     errh.ErrorExit(sig, "Incorrect type of space specified", ins);
  1953.   }
  1954.  
  1955. // The specified space must be unattached to another affine space, and
  1956. // we must be unattached:
  1957.  
  1958.   if (ins.HasSpace(AFFINE)) {
  1959.     errh.ErrorExit(sig, "Specified space already linked", ins);
  1960.   }
  1961.  
  1962.   if (this->HasSpace(rel)) {
  1963.     errh.ErrorExit(sig, "This space already linked", *this);
  1964.   }
  1965.  
  1966. // Dimensionality must match:
  1967.  
  1968.   int targetdim = ((rel == LINEARIZATION) ? ins.Dim() - 1 : ins.Dim());
  1969.   if (this->Dim() != targetdim) {
  1970.     errh.ErrorExit(sig, "Dimensions do not match", ins, *this);
  1971.   }
  1972.  
  1973. // If the other link of one is filled, the same link must be unfilled
  1974. // on the other:
  1975.  
  1976.   if ((ins.HasSpace(LINEARIZATION)) && (this->HasSpace(LINEARIZATION))) {
  1977.     errh.ErrorExit(sig, "Linked to mismatched linearizations", ins, *this);
  1978.   }  
  1979.   if ((ins.HasSpace(PROJECT_COMP)) && (this->HasSpace(PROJECT_COMP))) {
  1980.     errh.ErrorExit(sig, "Linked to mismatched proj. completions", ins, *this);
  1981.   }  
  1982.  
  1983. // Now check that the map we have been given fits the bill for stitching
  1984. // two spaces together.  The map must be affine:
  1985.  
  1986.   if (m.Holds() != AFF_MAP) {
  1987.     errh.ErrorExit(sig, "Map must be affine", ins, *this, m);
  1988.   }
  1989.  
  1990. // The range and domain must match the spaces we have:
  1991.  
  1992.   SubSet Rsub = m.Range();
  1993.   SubSet Dsub = m.Domain();
  1994.   Space Remb = Rsub.EmbeddingSpace();
  1995.   Space Demb = Dsub.EmbeddingSpace();
  1996.  
  1997.   if ((Remb != ins) || (Rsub.Dim() != this->Dim())) {
  1998.     errh.ErrorExit(sig, "Map Range/Dimension mismatch", ins, *this, m);
  1999.   }
  2000.   if ((Demb != *this) || (!Dsub.IsFullSpace())) {
  2001.     errh.ErrorExit(sig, "Map Domain/Dimension mismatch", ins, *this, m);
  2002.   }
  2003.  
  2004. // Install the standard linkage maps.  Do the set merging only after
  2005. // we have checked the state of the original sets for choosing:
  2006.  
  2007.   if (rel == LINEARIZATION) {
  2008.     if (ins.HasSpace(PROJECT_COMP)) {
  2009.       this->MergeSets(ins);
  2010.       this->LinkLAHaveLP(m.Inv());
  2011.     } else if (this->HasSpace(PROJECT_COMP)) {
  2012.       this->MergeSets(ins);
  2013.       this->LinkLAHaveAP(m.Inv());
  2014.     } else {
  2015.       this->MergeSets(ins);
  2016.       this->LinkLA(m.Inv());
  2017.     }
  2018.   } else {  // rel == PC
  2019.     if (ins.HasSpace(LINEARIZATION)) {
  2020.       this->MergeSets(ins);
  2021.       this->LinkAPHaveLP(m);
  2022.     } else if (this->HasSpace(LINEARIZATION)) {
  2023.       this->MergeSets(ins);
  2024.       this->LinkAPHaveLA(m);
  2025.     } else {
  2026.       this->MergeSets(ins);
  2027.       this->LinkAP(m);
  2028.     }
  2029.   }
  2030.   return (*this);
  2031. }
  2032.  
  2033. // ***********************************************************************
  2034. // 
  2035. // Construct a plain vanilla Affine space, with no attachments to
  2036. // other spaces: 
  2037. //
  2038.  
  2039. ASpace::ASpace(char* namein, int n, Boolean eflag) 
  2040. {
  2041.   static char* sig = "ASpace::ASpace(char*, int, Boolean)";
  2042.  
  2043.   if (n < 1) {
  2044.     errh.ErrorExit(sig, "Dimension is out of range", ErrVal("Dim = ", n));
  2045.   }
  2046.  
  2047. // Create a new SpaceInfo:
  2048.  
  2049.   info = new SpaceInfo;
  2050.   type = AFF_SPACE;
  2051.   holds = AFF_SPACE;
  2052.  
  2053. // Start to fill in the information:
  2054.  
  2055.   info->type = type;
  2056.   info->dim = n;
  2057.   info->matsize = info->dim + 1;
  2058.   info->native = AFF_POINT;
  2059.   info->thisSpace = AFFINE;
  2060.   info->stdBasis = Basis(FRAME, *this, n + 1);
  2061.   info->cpSize = 1;
  2062.   info->cpSlots = IntList(1);
  2063.   info->spaceSet[AFFINE] = *this;
  2064.   info->isEuclidean = eflag;
  2065.   this->CopyDebugName(namein);
  2066.  
  2067. // Need to construct the matrix that hoists tangent vectors into the
  2068. // internal affine space representation:
  2069.  
  2070.   info->hoistTangent = this->BuildHoist(info->dim);
  2071.  
  2072. // Build standard subsets:
  2073.  
  2074.   info->fullset = ASubSet(*this);
  2075.   info->stdAffineSet = info->fullset;
  2076. }
  2077.  
  2078. // ***********************************************************************
  2079. // 
  2080. // Build an affine space that is attached to specified vector and 
  2081. // projective spaces.  Stitch them together with standard maps:
  2082. //
  2083.  
  2084. ASpace::ASpace(char* namein, Boolean eflag, VSpace& v, PSpace& p)
  2085. {
  2086.   static char* sig = "ASpace::ASpace(char*, Boolean, VSpace&, PSpace&)";
  2087.  
  2088.   type = AFF_SPACE;
  2089.  
  2090. // Make sure that the various spaces specified have the correct dimension:
  2091.  
  2092.   if (v.Dim() != (p.Dim() + 1)) {
  2093.     errh.ErrorExit(sig, "Mismatch of dimensions", v, p);
  2094.   }
  2095.  
  2096. // The vector space must be a Linearization, not a dual or tangent space:
  2097.  
  2098.   if (v.ThisSpaceIs() != LINEARIZATION) {
  2099.     errh.ErrorExit(sig, "Vector space not a linearization", v);
  2100.   }
  2101.  
  2102. // The specified spaces must not be attached to an affine already:
  2103.  
  2104.   if (v.HasSpace(AFFINE) || p.HasSpace(AFFINE)) {
  2105.     errh.ErrorExit(sig, "One or more specified spaces already linked", v, p);
  2106.   }
  2107.  
  2108. // Start by constructing an unattached affine space:
  2109.  
  2110.   *this = ASpace(namein, p.Dim(), eflag); 
  2111.  
  2112. // Figure out if the specified spaces are unlinked or linked to each other,
  2113. // then link them if necessary:
  2114.  
  2115.   Boolean linkerr;
  2116.   Boolean linked = this->HaveLink(v, LINEARIZATION, p, PROJECT_COMP, &linkerr);
  2117.  
  2118.   if (linkerr) {
  2119.     errh.ErrorExit(sig, "Spaces must be unlinked or linked to each other",
  2120.            v, p);
  2121.   }
  2122.  
  2123.   if (!linked) {
  2124.     p.MergeSets(v);
  2125.     p.LinkLP(ProjectiveMap(v, p));
  2126.   }
  2127.  
  2128. // Broadcast this space:
  2129.  
  2130.   this->Broadcast(AFFINE, v);
  2131.  
  2132. // Install the standard maps:
  2133.  
  2134.   LinkLAHaveLP(AffineMap(v, *this));
  2135. }
  2136.  
  2137. // ***********************************************************************
  2138. // 
  2139. // Build an affine space that is attached to the specified space, which
  2140. // must be either vector or projective.  Stitch them together with
  2141. // standard maps:
  2142. //
  2143.  
  2144. ASpace::ASpace(char* namein, Boolean eflag, Space& ins) 
  2145. {
  2146.   static char* sig = "ASpace::ASpace(char*, Boolean, Space&)";
  2147.  
  2148.   type = AFF_SPACE;
  2149.  
  2150. // The specified space must be the right kind:
  2151.   
  2152.   SRel rel = ins.ThisSpaceIs();
  2153.  
  2154.   if ((rel != LINEARIZATION) && (rel != PROJECT_COMP)) {
  2155.     errh.ErrorExit(sig, "Incorrect type of space specified", ins);
  2156.   }
  2157.  
  2158. // The specified space must be unattached to another affine space.
  2159.  
  2160.   if (ins.HasSpace(AFFINE)) {
  2161.     errh.ErrorExit(sig, "Specified space already linked", ins);
  2162.   }
  2163.  
  2164. // Start by constructing an unattached affine space:
  2165.  
  2166.   int targetdim = ((rel == LINEARIZATION) ? ins.Dim() - 1 : ins.Dim());
  2167.   *this = ASpace(namein, targetdim, eflag); 
  2168.  
  2169. // Broadcast the space:
  2170.  
  2171.   this->Broadcast(AFFINE, ins);
  2172.  
  2173. // Install the standard maps:
  2174.  
  2175.   if (rel == LINEARIZATION) {
  2176.     if (ins.HasSpace(PROJECT_COMP)) {
  2177.       LinkLAHaveLP(AffineMap(ins, *this));
  2178.     } else {
  2179.       LinkLA(AffineMap(ins, *this));
  2180.     }
  2181.   } else { // rel = PROJECT_COMP
  2182.     if (ins.HasSpace(LINEARIZATION)) {
  2183.       LinkLAHaveLP(AffineMap(ins.GetSpace(LINEARIZATION), *this));
  2184.     } else {
  2185.       LinkAP(AffineMap(*this, ins));
  2186.     }
  2187.   }
  2188. }
  2189.  
  2190. // ***********************************************************************
  2191. //
  2192. // This constructor is used to build Cartesian Product spaces from
  2193. // a list of existing spaces.  The space that results is a bare space;
  2194. // no other spaces are linked to it.
  2195. //
  2196.  
  2197. ASpace::ASpace(char *namein, SpaceList& t, Boolean eflag)
  2198. {
  2199.   int i;
  2200.  
  2201.   static char* sig = "ASpace::ASpace(char*, SpaceList&, Boolean)";
  2202.  
  2203. // Error if no spaces in the list, or if one space in list (cannot
  2204. // create aliases for atomic spaces):
  2205.  
  2206.   if (t.Length() <= 1) {
  2207.     errh.ErrorExit(sig, "Not enough spaces in space list", t);
  2208.   }
  2209.  
  2210. // Create a new SpaceInfo:
  2211.  
  2212.   info = new SpaceInfo;
  2213.   type = AFF_SPACE;
  2214.   holds = AFF_SPACE;
  2215.  
  2216. // All the spaces in the list must be affine spaces.  The dimension
  2217. // of this space is the sum of the dimensions of the spaces in the
  2218. // list.  The cardinality of this space is the sum of the 
  2219. // cardinalities of the spaces in the list (spaces in the list
  2220. // may themselves be CPSpaces).
  2221.  
  2222.   info->dim = 0;
  2223.   info->cpSize = 0;
  2224.   for (i = 0; i < t.Length(); i++) {
  2225.     Space hold = t[i];
  2226.     if (hold.Holds() != AFF_SPACE) {
  2227.       errh.ErrorExit(sig, "Non-affine space in space list", t);
  2228.     }
  2229.     info->dim += hold.Dim();
  2230.     info->cpSize += hold.CPSpaceSize();
  2231.   }
  2232.  
  2233. // Build the necessary lists and go through the space list once more,
  2234. // filling in as we go:
  2235.  
  2236.   info->cpSpaces = SpaceList(info->cpSize);
  2237.   info->cpSlots = IntList(info->cpSize);
  2238.   int slot = 0;
  2239.   int dim_sum = 0;
  2240.  
  2241.   for (i = 0; i < t.Length(); i++) {
  2242.     Space hold = t[i];
  2243.     for (int j = 0; j < hold.CPSpaceSize(); j++) {   
  2244.       (info->cpSpaces)[slot] = hold[j];
  2245.       (info->cpSlots)[slot++] = dim_sum;
  2246.       dim_sum += (hold[j]).Dim();
  2247.     }
  2248.   }  
  2249.  
  2250. // Misc. info:
  2251.  
  2252.   info->matsize = info->dim + 1;
  2253.   info->native = AFF_POINT;
  2254.   info->type = type;
  2255.   info->thisSpace = AFFINE;
  2256.   info->stdBasis = Basis(FRAME, *this, info->dim + 1);
  2257.   info->spaceSet[AFFINE] = *this;
  2258.   info->isEuclidean = eflag;
  2259.   this->CopyDebugName(namein);
  2260.  
  2261. // Need to construct the matrix that hoists tangent vectors into the
  2262. // internal affine space representation:
  2263.  
  2264.   info->hoistTangent = this->BuildHoist(info->dim);
  2265.  
  2266. // Build standard subsets:
  2267.  
  2268.   info->fullset = ASubSet(*this);
  2269.   info->stdAffineSet = info->fullset;
  2270. }
  2271.  
  2272. // ***********************************************************************
  2273. // ***********************************************************************
  2274. //
  2275. // PSpace Class
  2276. //
  2277. // ***********************************************************************
  2278.  
  2279. // ***********************************************************************
  2280. //
  2281. // Public member functions
  2282. //
  2283. // ***********************************************************************
  2284. //
  2285. // Used for downcasting:
  2286. //
  2287.  
  2288. PSpace::PSpace(Space& s) : (s)
  2289. {
  2290.   type = PROJ_SPACE;
  2291.   if ((holds != PROJ_SPACE) && (holds != NULL_SPACE)) {
  2292.       errh.ErrorExit("PSpace::PSpace(Space&)",
  2293.                      "Attempted to cast a non-proj. space to a proj. space",
  2294.              s);
  2295.   }
  2296. }
  2297.  
  2298. // ***********************************************************************
  2299. //
  2300. // Assignment:
  2301. //
  2302.  
  2303. PSpace& PSpace::operator=(PSpace &s)
  2304. {
  2305.   holds = s.holds;
  2306.   info = s.info;
  2307.   return (*this);
  2308. }
  2309.  
  2310. // ***********************************************************************
  2311. //
  2312. // Output for debugging:
  2313. //
  2314.  
  2315. void PSpace::debug_out(ostream &c, int indent)
  2316. {
  2317.   static char* name = "PSpace Object\n";
  2318.   this->data_out(c, indent, name);
  2319.   return;
  2320. }
  2321.  
  2322. // ***********************************************************************
  2323. // 
  2324. // Stitches the given space into this space using the user specified map:
  2325. //
  2326.  
  2327. Space PSpace::SetSpace(Space& ins, Map& m)
  2328. {
  2329.   static char* sig = "void PSpace::SetSpace(Space&, Map&)";
  2330.  
  2331. // Start by enforcing restrictions on the spaces.
  2332. // The specified space must be the right kind:
  2333.   
  2334.   SRel rel = ins.ThisSpaceIs();
  2335.  
  2336.   if ((rel != AFFINE) && (rel != LINEARIZATION)) {
  2337.     errh.ErrorExit(sig, "Incorrect type of space specified", ins);
  2338.   }
  2339.  
  2340. // The specified space must be unattached to another PC space, and
  2341. // we must be unattached:
  2342.  
  2343.   if (ins.HasSpace(PROJECT_COMP)) {
  2344.     errh.ErrorExit(sig, "Specified space already linked", ins);
  2345.   }
  2346.  
  2347.   if (this->HasSpace(rel)) {
  2348.     errh.ErrorExit(sig, "This space already linked", *this);
  2349.   }
  2350.  
  2351. // Dimensionality must match:
  2352.  
  2353.   int targetdim = ((rel == LINEARIZATION) ? ins.Dim() - 1 : ins.Dim());
  2354.   if (this->Dim() != targetdim) {
  2355.     errh.ErrorExit(sig, "Dimensions do not match", ins, *this);
  2356.   }
  2357.  
  2358. // If the other link of one is filled, the same link must be unfilled
  2359. // on the other:
  2360.  
  2361.   if ((ins.HasSpace(AFFINE)) && (this->HasSpace(AFFINE))) {
  2362.     errh.ErrorExit(sig, "Linked to mismatched affine spaces", ins, *this);
  2363.   }  
  2364.   if ((ins.HasSpace(LINEARIZATION)) && (this->HasSpace(LINEARIZATION))) {
  2365.     errh.ErrorExit(sig, "Linked to mismatched linearizations", ins, *this);
  2366.   }  
  2367.  
  2368. // Now check that the map we have been given fits the bill for stitching
  2369. // two spaces together.  If the given space is affine, the map must be
  2370. // affine; if linear, the map must be projective:
  2371.  
  2372.   if ((rel == AFFINE) && (m.Holds() != AFF_MAP)) {
  2373.     errh.ErrorExit(sig, "Map must be affine", ins, *this, m);
  2374.   }
  2375.  
  2376.   if ((rel == LINEARIZATION) && (m.Holds() != PROJ_MAP)) {
  2377.     errh.ErrorExit(sig, "Map must be projective", ins, *this, m);
  2378.   }
  2379.  
  2380. // The range and domain must match the spaces we have:
  2381.  
  2382.   SubSet Rsub = m.Range();
  2383.   SubSet Dsub = m.Domain();
  2384.   Space Remb = Rsub.EmbeddingSpace();
  2385.   Space Demb = Dsub.EmbeddingSpace();
  2386.  
  2387.   if ((Remb != ins) || (!Rsub.IsFullSpace())) {
  2388.     errh.ErrorExit(sig, "Map Range/Dimension mismatch", ins, *this, m);
  2389.   }
  2390.   if ((rel == AFFINE) &&
  2391.       ((Demb != *this) || (Dsub.Dim() != ins.Dim()))) {
  2392.     errh.ErrorExit(sig, "Map Domain/Dimension mismatch", ins, *this, m);
  2393.   }
  2394.   if ((rel == LINEARIZATION) &&
  2395.       ((Demb != *this) || (Dsub.Dim() != ins.Dim() - 1))) {
  2396.     errh.ErrorExit(sig, "Map Domain/Dimension mismatch", ins, *this, m);
  2397.   }
  2398.  
  2399. // Install the standard linkage maps.  Do the set merging only after
  2400. // we have checked the state of the original sets for choosing:
  2401.  
  2402.   if (rel == AFFINE) {
  2403.     if (this->HasSpace(LINEARIZATION)) {
  2404.       this->MergeSets(ins);
  2405.       LinkAPHaveLP(m.Inv());
  2406.     } else if (ins.HasSpace(LINEARIZATION)) {
  2407.       this->MergeSets(ins);
  2408.       LinkAPHaveLA(m.Inv());
  2409.     } else {
  2410.       this->MergeSets(ins);
  2411.       LinkAP(m.Inv());
  2412.     }
  2413.   } else {  // rel == LINEARIZATION
  2414.     if (this->HasSpace(AFFINE)) {
  2415.       this->MergeSets(ins);
  2416.       LinkLPHaveAP(m.Inv());
  2417.     } else if (ins.HasSpace(AFFINE)) {
  2418.       this->MergeSets(ins);
  2419.       LinkLPHaveLA(m.Inv());
  2420.     } else {
  2421.       this->MergeSets(ins);
  2422.       LinkLP(m.Inv());
  2423.     }
  2424.   }
  2425.   return (*this);
  2426. }
  2427.  
  2428. // ***********************************************************************
  2429. // 
  2430. // Construct a plain vanilla projective space, with no attachments to
  2431. // other spaces: 
  2432. //
  2433.  
  2434. PSpace::PSpace(char *namein, int n)
  2435. {
  2436.   static char* sig = "PSpace::PSpace(char*, int)";
  2437.  
  2438.   if (n < 1) {
  2439.     errh.ErrorExit(sig, "Dimension is out of range", ErrVal("Dim = ", n));
  2440.   }
  2441.  
  2442. // Create a new SpaceInfo:
  2443.  
  2444.   info = new SpaceInfo;
  2445.   type = PROJ_SPACE;
  2446.   holds = PROJ_SPACE;
  2447.  
  2448. // Fill in all the pertinent information:
  2449.  
  2450.   info->type = type;
  2451.   info->dim = n;
  2452.   info->matsize = info->dim + 1;
  2453.   info->native = PROJ_POINT;
  2454.   info->thisSpace = PROJECT_COMP;
  2455.   info->stdBasis = Basis(HFRAME, *this, n + 1);
  2456.   info->spaceSet[PROJECT_COMP] = *this;
  2457.   info->isEuclidean = FALSE;
  2458.   info->cpSize = 1;
  2459.   info->cpSlots = IntList(1);
  2460.   this->CopyDebugName(namein);
  2461.  
  2462. // Build standard subsets:
  2463.  
  2464.   info->fullset = PSubSet(*this);
  2465.   info->fullproj = info->fullset;
  2466. }
  2467.  
  2468. // ***********************************************************************
  2469. // 
  2470. // Build a projective space that is attached to specified vector and 
  2471. // affine spaces.  Stitch them together with standard maps:
  2472. //
  2473.  
  2474. PSpace::PSpace(char* namein, VSpace& v, ASpace& a)
  2475. {
  2476.   static char* sig = "PSpace::PSpace(char*, VSpace&, ASpace&)";
  2477.  
  2478.   type = PROJ_SPACE;
  2479.  
  2480. // Make sure that the various spaces specified have the correct dimension:
  2481.  
  2482.   if (v.Dim() != (a.Dim() + 1)) {
  2483.     errh.ErrorExit(sig, "Mismatch of dimensions", v, a);
  2484.   }
  2485.  
  2486. // The vector space must be a Linearization, not a dual or tangent space:
  2487.  
  2488.   if (v.ThisSpaceIs() != LINEARIZATION) {
  2489.     errh.ErrorExit(sig, "Vector space not a linearization", v);
  2490.   }
  2491.  
  2492. // The specified spaces must be unattached to PCs:
  2493.  
  2494.   if (v.HasSpace(PROJECT_COMP) || a.HasSpace(PROJECT_COMP)) {
  2495.     errh.ErrorExit(sig, "One or more specified spaces already linked", v, a);
  2496.   }
  2497.  
  2498. // Start by constructing an unattached projective space:
  2499.  
  2500.   *this = PSpace(namein, a.Dim()); 
  2501.  
  2502. // Figure out if the specified spaces are unlinked or linked to each other,
  2503. // then link them if necessary:
  2504.  
  2505.   Boolean linkerr;
  2506.   Boolean linked = this->HaveLink(a, AFFINE, v, LINEARIZATION, &linkerr);
  2507.  
  2508.   if (linkerr) {
  2509.     errh.ErrorExit(sig, "Spaces must be unlinked or linked to each other",
  2510.            a, v);
  2511.   }
  2512.  
  2513.   if (!linked) {
  2514.     v.MergeSets(a);
  2515.     v.LinkLA(AffineMap(v, a));
  2516.   }
  2517.  
  2518. // Broadcast this space:
  2519.  
  2520.   this->Broadcast(PROJECT_COMP, a);
  2521.  
  2522. // Install the standard maps:
  2523.  
  2524.   LinkAPHaveLA(AffineMap(a, *this));
  2525. }
  2526.  
  2527. // ***********************************************************************
  2528. // 
  2529. // Build a projective space that is attached to the specified space, which
  2530. // must be either vector or affine.  Stitch them together with
  2531. // standard maps:
  2532. //
  2533.  
  2534. PSpace::PSpace(char* namein, Space& ins) 
  2535. {
  2536.   static char* sig = "PSpace::PSpace(char*, Space&)";
  2537.  
  2538.   type = PROJ_SPACE;
  2539.  
  2540. // The specified space must be the right kind:
  2541.   
  2542.   SRel rel = ins.ThisSpaceIs();
  2543.  
  2544.   if ((rel != LINEARIZATION) && (rel != AFFINE)) {
  2545.     errh.ErrorExit(sig, "Incorrect type of space specified", ins);
  2546.   }
  2547.  
  2548. // The specified space must be unattached to another projective space.
  2549.  
  2550.   if (ins.HasSpace(PROJECT_COMP)) {
  2551.     errh.ErrorExit(sig, "Specified space already linked", ins);
  2552.   }
  2553.  
  2554. // Start by constructing an unattached affine space:
  2555.  
  2556.   int targetdim = ((rel == LINEARIZATION) ? ins.Dim() - 1 : ins.Dim());
  2557.   *this = PSpace(namein, targetdim); 
  2558.  
  2559. // Broadcast the space:
  2560.  
  2561.   this->Broadcast(PROJECT_COMP, ins);
  2562.  
  2563. // Install the standard maps:
  2564.  
  2565.   if (rel == AFFINE) {
  2566.     if (ins.HasSpace(LINEARIZATION)) {
  2567.       LinkAPHaveLA(AffineMap(ins, *this));
  2568.     } else {
  2569.       LinkAP(AffineMap(ins, *this));
  2570.     }
  2571.   } else { // rel = LINEARIZATION
  2572.     if (ins.HasSpace(AFFINE)) {
  2573.       LinkAPHaveLA(AffineMap(ins.GetSpace(AFFINE), *this));
  2574.     } else {
  2575.       LinkLP(ProjectiveMap(ins, *this));
  2576.     }
  2577.   }
  2578. }
  2579.  
  2580.  
  2581. // ***********************************************************************
  2582. // ***********************************************************************
  2583. //
  2584. // Create the error information block:
  2585. //
  2586.  
  2587. static SpaceInfo errInfo("Uninitialized Space", 0);
  2588.  
  2589. // ***********************************************************************
  2590. //
  2591. // Create the vector space for Real numbers:
  2592. //
  2593.  
  2594. VSpace Reals("Real Numbers", 1, FALSE);
  2595.  
  2596. // ***********************************************************************
  2597.